package scparser.factory.primitiveFactory;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.vecmath.Point3d;


import scparser.ParserHelper;
import lib.common.Constants;
import model.Scene;
import model.primitive.Primitive;
import model.shader.Shader;

public abstract class PrimitiveFactory implements PrimitiveAbstractFactory{
	
	protected Scene scene;
	protected String name;
	protected Shader shader;
	protected Point3d translate;
	protected Double rotatex;
	protected Double rotatey;
	protected Double rotatez;
	protected Double scaleu;
	protected Double scalex;
	protected Double scaley;
	protected Double scalez;
	protected boolean transformPresent = false;


	@Override
	public abstract Primitive create(List<String> block) throws FactoryException;
	
	protected Shader getShader(String shaderName) {
		Iterator<Shader> it = this.scene.getShaders().iterator();
		while (it.hasNext()) {
			Shader next = it.next();
			if (next.getName().equals(shaderName)) {
				return next;
			}
		}
		return null;
	}
	
	public void parseTransform(String line) throws IOException {
		// single line and only one property (translate or rotate)
		int begin = line.indexOf("{") + 1;
		
		String property = line.substring(begin).trim();
		
		if (property.startsWith("translate")) {
			setTranslate(ParserHelper.takePoint(property, "translate"));
		} else if (property.startsWith("rotatex")) {
			setRotatex(ParserHelper.takeDouble(property,"rotatex"));
		} else if (property.startsWith("rotatey")) {
			setRotatey(ParserHelper.takeDouble(property,"rotatey"));
		} else if (property.startsWith("rotatez")) {
			setRotatez(ParserHelper.takeDouble(property,"rotatez"));
		} else if (property.startsWith("scalex")) {
			setScalex(ParserHelper.takeDouble(property,"scalex"));
		} else if (property.startsWith("scaley")) {
			setScaley(ParserHelper.takeDouble(property,"scaley"));
		} else if (property.startsWith("scalez")) {
			setScalez(ParserHelper.takeDouble(property,"scalez"));
		} else if (property.startsWith("scaleu")) {
			setScaleu(ParserHelper.takeDouble(property,"scaleu"));
		}
		
		this.transformPresent = true;
	}
	
	public void parseTransform(Iterator<String> it) throws IOException {
		String transformLine;
		while (it.hasNext()) {
			transformLine = it.next().trim();
			
			if (transformLine.startsWith("translate")) {
				setTranslate(ParserHelper.takePoint(transformLine, "translate"));
			} else if (transformLine.startsWith("rotatex")) {
				setRotatex(ParserHelper.takeDouble(transformLine,"rotatex"));
			} else if (transformLine.startsWith("rotatey")) {
				setRotatey(ParserHelper.takeDouble(transformLine,"rotatey"));
			} else if (transformLine.startsWith("rotatez")) {
				setRotatez(ParserHelper.takeDouble(transformLine,"rotatez"));
			} else if (transformLine.startsWith("scalex")) {
				setScalex(ParserHelper.takeDouble(transformLine,"scalex"));
			} else if (transformLine.startsWith("scaley")) {
				setScaley(ParserHelper.takeDouble(transformLine,"scaley"));
			} else if (transformLine.startsWith("scalez")) {
				setScalez(ParserHelper.takeDouble(transformLine,"scalez"));
			} else if (transformLine.startsWith("scaleu")) {
				setScaleu(ParserHelper.takeDouble(transformLine,"scaleu"));
			} else if (transformLine.startsWith(Constants.S_CLOSE)) {
				break;
			}
		}
		
		this.transformPresent = true;
	}
	
	public Primitive transform( Primitive p ){
		p.translate(this.translate);
		p.rotatex(this.rotatex);
		p.rotatey(this.rotatey);
		p.rotatez(this.rotatez);
		p.scalex(this.scalex);
		p.scaley(this.scaley);
		p.scalez(this.scalez);
		p.scaleu(this.scaleu);
		return p;
	}

	public void setTranslate(Point3d pos) {
		this.translate = pos;
	}

	public void setRotatex(Double d) {
		this.rotatex = d;
	}

	public void setScaleu(Double s) {
		this.scaleu=s;
	}

	public void setRotatey(Double d) {
		this.rotatey=d;
	}

	public void setRotatez(Double d) {
		this.rotatez=d;
	}

	public void setScalex(Double s) {
		this.scalex=s;
	}

	public void setScaley(Double s) {
		this.scaley=s;
	}

	public void setScalez(Double s) {
		this.scalez=s;
	}


}
